perm filename DEVIND.SAI[S,HE]1 blob sn#498961 filedate 1982-04-13 generic text, type C, neo UTF8
COMMENT ⊗   VALID 00013 PAGES
C REC  PAGE   DESCRIPTION
C00001 00001
C00003 00002	ENTRY DDDEV,FILDEV,XGPDEV,GRNDEV,DOVDEV,CANDEV,PICDEV,SYNDEV,LINE,SEE,SETCLR
C00007 00003	INTEGER PROCEDURE NEWPIC(INTEGER HEIGHT,WIDTH,BITS)
C00008 00004	INTERNAL INTEGER PROCEDURE DDDEV
C00009 00005	INTERNAL INTEGER PROCEDURE XGPDEV
C00011 00006	INTERNAL INTEGER PROCEDURE DOVDEV
C00012 00007	INTERNAL INTEGER PROCEDURE SYNDEV
C00013 00008	Routines for doing picture graphics.  These were stolen with minor
C00015 00009	INTERNAL PROCEDURE LINE(INTEGER D REAL X1,Y1,X2,Y2)
C00021 00010	INTERNAL PROCEDURE DOT(INTEGER D REAL X,Y)
C00030 00011	INTERNAL PROCEDURE SEE(INTEGER D)
C00039 00012	INTERNAL PROCEDURE SETCLR(INTEGER C)
C00040 00013	END "DEVIND"
C00041 ENDMK
C⊗;
ENTRY DDDEV,FILDEV,XGPDEV,GRNDEV,DOVDEV,CANDEV,PICDEV,SYNDEV,LINE,SEE,SETCLR;

COMMENT These routines are for the device-independent graphics package.;

BEGIN "DEVIND"

COMMENT For ADDIEL;
REQUIRE "DEVINS.REL[GRA,AAM]" LOAD_MODULE;
COMMENT For PIXDIM,MAKPIX,LNBY et al;
REQUIRE "PIXHDR.SAI[VIS,HPM]" SOURCE_FILE;
COMMENT For GDDCHN,SHOWA,SYNMAP;
    COMMENT REQUIRE "DDHDR.SAI[GRA,HPM]" SOURCE_FILE;
    COMMENT These defn's here 'cause we redefine LINE etc.;
    REQUIRE "DDSAI[gra,hpm]" LIBRARY;
    REQUIRE "DDFAI[gra,hpm]" LIBRARY;
    EXTERNAL BOOLEAN PROCEDURE MAPMON(REAL GAMMA; INTEGER RESET(0));
    external integer PROCEDURE SYNMAP(INTEGER ORD,reset(0));
    EXTERNAL PROCEDURE SHOWA(INTEGER CHAN,console(-1));  comment add chan to console;
    EXTERNAL INTEGER PROCEDURE GDDCHN(INTEGER CHAN(-1));
COMMENT For FILE_LINE,FILE_SEE,FILE_DOT;
REQUIRE "FILHDR.SAI[GRA,AAM]" SOURCE_FILE;
COMMENT For GRNLIN,GRNDOT;
REQUIRE "GRNGRA.SAI[GRA,AAM]" SOURCE_FILE;

COMMENT Device identifiers;
DEFINE  DD = 1,
	FILE = 2,
	XGP = 3,
	GRINNELL = 4,
	DOVER = 5,
	CANON = 6,
	PICTURE = 7,
	SYNTHESIZER = 8;

DEFINE  CRLF = "'15&'12";

COMMENT Color of graphics;
REAL COLOR;

COMMENT Device table;
DEFINE  DEVTBSIZE = 100;
INTEGER ARRAY DEVTAB[0:DEVTBSIZE-1];
INTEGER DEVUSED;

COMMENT Grinnell line buffer;
DEFINE  GLBUFSIZE = 100;
REAL ARRAY LINEBUF[0:GLBUFSIZE-1,1:4];
INTEGER GLBUF;

COMMENT Grinnell dot buffer;
DEFINE  GDBUFSIZE = 100;
REAL ARRAY DOTBUF[0:GDBUFSIZE-1,1:2];
INTEGER GDBUF;

PROCEDURE DENTER(INTEGER NUM);
COMMENT Make an entry into the device table at the current position.;
BEGIN "DENTER"
IF DEVUSED > DEVTBSIZE THEN PRINT("Device table overflow...too many graphics"&
	" output devices"&CRLF)
ELSE
    BEGIN
	DEVTAB[DEVUSED] ← NUM;
	DEVUSED ← DEVUSED + 1
    END
END "DENTER";
INTEGER PROCEDURE NEWPIC(INTEGER HEIGHT,WIDTH,BITS);
COMMENT Make a new picture which is HEIGHT by WIDTH and has BITS bits per
	pixel.  The routine returns the address of the picture.
NOTE that this will quite likely have to be changed when multiple languages are
accomodated.;
BEGIN "NEWPIC"
EXTERNAL INTEGER PROCEDURE ARMAK(INTEGER LB,UB,DIMS);
INTEGER PICADDRESS;

PICADDRESS ← ARMAK(0,PIXDIM(HEIGHT,WIDTH,BITS),1);
MAKPIX(HEIGHT,WIDTH,BITS,MEMORY[PICADDRESS]);
RETURN(PICADDRESS)

END "NEWPIC";
INTERNAL INTEGER PROCEDURE DDDEV;
BEGIN "DDDEV"
COMMENT Initialize a DD channel.;
INTEGER C,D;

D ← DEVUSED;
DENTER(DD);			COMMENT Device table contains "DD";
 DENTER(NEWPIC(480,512,1));	COMMENT and buffer address (buffer is 1-bit pic);
 DENTER(-2);			COMMENT channel in use (-2 means none picked yet);
RETURN(D)

END "DDDEV";



INTERNAL INTEGER PROCEDURE FILDEV(INTEGER IOCHAN);
BEGIN "FILDEV"
COMMENT Initialize a file.;
INTEGER D;

D ← DEVUSED;
DENTER(FILE); DENTER(IOCHAN);	COMMENT Device table contains "FILE" and io chan;
RETURN(D)

END "FILDEV";
INTERNAL INTEGER PROCEDURE XGPDEV;
COMMENT Initialize the XGP for output.;
BEGIN "XGPDEV"
INTEGER D;

PRINT("Sorry.  XGP graphics are not currently implemented."&CRLF);
D ← DEVUSED;
DENTER(XGP);		COMMENT Device table contains "XGP";
RETURN(D)

END "XGPDEV";



INTERNAL INTEGER PROCEDURE GRNDEV;
COMMENT Initialize the Grinnell for output...no big deal yet.;
BEGIN "GRNDEV"
INTEGER D;

PRINT("NOTE:  Grinnell is currently single-user mode...take your chances."&CRLF);
D ← DEVUSED;
DENTER(GRINNELL);	COMMENT Device table contains "GRINNELL";
 DENTER(1);		COMMENT and channel no.;
 DENTER('7777);		COMMENT and subchannel mask;
RETURN(D)

END "GRNDEV";
INTERNAL INTEGER PROCEDURE DOVDEV;
COMMENT Initialize dover for graphics.;
BEGIN "DOVDEV"
INTEGER D;

PRINT("Sorry.  Dover output is not currently implemented."&CRLF);
D ← DEVUSED;
DENTER(DOVER);
RETURN(D)

END "DOVDEV";


INTERNAL INTEGER PROCEDURE CANDEV;
COMMENT Initialize Canon for graphics.;
BEGIN "CANDEV"
INTEGER D;

PRINT("Sorry.  Canon output is not currently implemented."&CRLF);
D ← DEVUSED;
DENTER(CANON);
RETURN(D)

END "CANDEV";
INTERNAL INTEGER PROCEDURE SYNDEV;
COMMENT Initialize the synthesizer for graphics.;
BEGIN "SYNDEV"
INTEGER D;

D ← DEVUSED;
DENTER(SYNTHESIZER);		COMMENT Device table contains "SYNTHESIZER";
 DENTER(NEWPIC(480,512,8));	COMMENT and the address of the 8-bit pic buffer;
RETURN(D)

END "SYNDEV";



INTERNAL INTEGER PROCEDURE PICDEV(REFERENCE INTEGER PIC);
COMMENT Make graphics go into an incore picture;
BEGIN "PICDEV"
INTEGER D;

D ← DEVUSED;
DENTER(PICTURE); DENTER(LOCATION(PIC));
RETURN(D)

END "PICDEV";
COMMENT Routines for doing picture graphics.  These were stolen with minor
	modification, from H. P. Moravec.;

PROCEDURE THIN(INTEGER PIC; REAL X1,Y1,X2,Y2);
   BEGIN "THIN"
   REAL LEN,DX,DY; REAL I,MODHALF; INTEGER I2LEN;
  COMMENT Get position of endpoints in pixel coords.;
   X1←(MEMORY[PIC+LNBY]-1.0)*X1;
   Y1←(MEMORY[PIC+PCLN]-1.0)*Y1;
   X2←(MEMORY[PIC+LNBY]-1.0)*X2;
   Y2←(MEMORY[PIC+PCLN]-1.0)*Y2;
  COMMENT LEN is length of line to draw, and MODHALF is LEN mod 0.5;
   DX←X2-X1; DY←Y2-Y1;
   LEN←SQRT(DX↑2+DY↑2);
   I2LEN ← LEN*2;
   MODHALF ← (LEN*2 - I2LEN)/2;
   DX←DX/LEN; DY←DY/LEN;
  COMMENT Plot points at each half-pixel with half brightness;
   FOR I←0 STEP 0.5 UNTIL LEN DO
      ADDIEL(MEMORY[PIC],Y1+DY*I,X1+DX*I,COLOR/2);
  COMMENT And plot the last point with the appropriate brightness;
   ADDIEL(MEMORY[PIC],Y2,X2,MODHALF*COLOR);
   END "THIN";
INTERNAL PROCEDURE LINE(INTEGER D; REAL X1,Y1,X2,Y2);
COMMENT Draw a line from x1,y1 to x2,y2 in normalized device coordinates on
	device D. ;
BEGIN "LINE"

CASE DEVTAB[D] OF BEGIN "DEVICE CASES"

[FILE] BEGIN				COMMENT Output the calling params;
	INTEGER C;
	C ← DEVTAB[D+1];
	WORDOUT(C,FILE_LINE);
	WORDOUT(C,X1);
	WORDOUT(C,Y1);
	WORDOUT(C,X2);
	WORDOUT(C,Y2)
       END;

[XGP];					COMMENT Unimplemented;

[GRINNELL] BEGIN			COMMENT Buffer a set of lines for CR's rtn.;
	LINEBUF[GLBUF,1] ← X1;
	LINEBUF[GLBUF,2] ← Y1;
	LINEBUF[GLBUF,3] ← X2;
	LINEBUF[GLBUF,4] ← Y2;
	GLBUF ← GLBUF+1;
	IF GLBUF > GLBUFSIZE THEN
	    BEGIN
		GRNLINE(D,LINEBUF,GLBUFSIZE);
		GLBUF ← 1
	    END
	END;

[DOVER];				COMMENT Unimplemented;

[CANON];				COMMENT Unimplemented;

[DD]					COMMENT Draw a thin line;
[PICTURE]
[SYNTHESIZER]				COMMENT SAIL bug means SYNTHESIZER last;
	THIN(DEVTAB[D+1],X1,Y1,X2,Y2)

END "DEVICE CASES"
END "LINE";
INTERNAL PROCEDURE DOT(INTEGER D; REAL X,Y);
COMMENT Make a point on device D. at x,y;
BEGIN "DOT"

CASE DEVTAB[D] OF BEGIN		"DEVICE CASES"
[FILE] BEGIN			 	COMMENT Output the calling params;
	INTEGER CHAN;
	CHAN ← DEVTAB[D+1];

	WORDOUT(CHAN,FILE_DOT);
	WORDOUT(CHAN,X);
	WORDOUT(CHAN,Y)
	END;

[XGP];					COMMENT Unimplemented;

[GRINNELL] BEGIN			COMMENT Buffer a set of dots for CR's rtn.;
	DOTBUF[GDBUF,1] ← X;
	DOTBUF[GDBUF,2] ← Y;
	GDBUF ← GDBUF+1;
	IF GDBUF > GDBUFSIZE THEN
	    BEGIN
		GRNDOT(D,DOTBUF,GDBUFSIZE);
		GDBUF ← 1
	    END
	END;

[DOVER];				COMMENT Unimplemented;

[CANON];				COMMENT Unimplemented;

[DD] [SYNTHESIZER]			COMMENT Put an interpolated dot into the
						picture.;
	ADDIEL(MEMORY[DEVTAB[D+1]],Y*479.0,X*511.0,COLOR);

[PICTURE] BEGIN				COMMENT Another interpolated dot...;
	INTEGER PIC;

	PIC ← DEVTAB[D+1];
	ADDIEL(MEMORY[PIC],Y*(MEMORY[PIC+PCLN,INTEGER]-1.0),
			   X*(MEMORY[PIC+LNBY,INTEGER]-1.0),COLOR)
	END

END "DEVICE CASES"
END "DOT";
INTERNAL PROCEDURE SEE(INTEGER D);
COMMENT Make graphics visible on device D.;
BEGIN "SEE"
COMMENT DD buffer has 480 lines, each line has 16 graphics words, a line
    select, and an execute.  The whole picture has 2 extra words: a channel/mode
    select and a halt.;
DEFINE DDBUFSIZE = "480*18+2";		COMMENT DD Buffer size;
INTEGER ARRAY DDBUF[0:DDBUFSIZE-1];
OWN INTEGER ARRAY CTLBLK[0:3];
INTEGER BUFPTR;

COMMENT Put a word into the DD buffer;
    PROCEDURE INSERT(INTEGER WORD);
	BEGIN "INSERT"
	    DDBUF[BUFPTR] ← WORD;
	    BUFPTR ← BUFPTR + 1
	END "INSERT";

CASE DEVTAB[D] OF BEGIN		"DEVICE CASES"
[FILE] WORDOUT(DEVTAB[D+1],FILE_SEE);	COMMENT Output the calling params;

[XGP];					COMMENT Unimplemented;

[GRINNELL] BEGIN			COMMENT Flush all buffers associated with
						the Grinnell;
    COMMENT Flush line buffer;
	GLBUF ← GLBUF-1;
	IF GLBUF > 0 THEN
	    GRNLINE(D,LINEBUF,GLBUF);
	GLBUF ← 1;
	END;

[DOVER];				COMMENT Unimplemented;

[CANON];				COMMENT Unimplemented;

[DD] BEGIN "DD OUTPUT"			COMMENT Make a DD instruction set from a
						one-bit picture.;
    INTEGER CHAN,BP,I,J,WORD,SC;
    INTEGER LINE,STARTLINE;

    COMMENT Start by getting output channel and setting mode.;
	IF DEVTAB[D+2] = -2 THEN DEVTAB[D+2] ← GDDCHN; COMMENT -2 means none yet;
	CHAN ← DEVTAB[D+2];
	BUFPTR ← 0;
	COMMENT -1 channel means our own, DD can't use 0;
	SC ← IF CHAN < 0 THEN 0 ELSE IF CHAN = 0 THEN '40 ELSE CHAN;
	INSERT((SC ROT -8) + (2 ROT -27)	COMMENT Select channel;
	     + (7 ROT -16) + (1 ROT -30)	COMMENT Set functions: dark back,
							write enb, graphic mode;
	     + (2 ROT -33)			COMMENT no-op (sel. ch. 0);
	     + 4);				COMMENT Command word opcode;

    COMMENT Now display all the lines in 4 sets.  This is the only way the
	timing will work properly on the Datadisc.;
	FOR STARTLINE ← 0 STEP 1 UNTIL 3 DO
	    FOR LINE ← STARTLINE STEP 4 UNTIL 479 DO
		BEGIN "LINE OUTPUT"
		    INSERT(((LINE LSH -4) ROT -8) + (4 ROT -27) COMMENT Hi line ad;
			 + ((LINE LAND '17) ROT -16) + (5 ROT -30) COMMENT Lo ad;
			 + (1 ROT -24) + (3 ROT -33)	COMMENT Select col 1;
			 + 4);				COMMENT Command word;
		COMMENT For each line, use a byte pointer to extract 32-bit hunks
			and put them into the DD buffer.  One line has 16 such
			hunks.;
		    BP ← POINT(4,MEMORY[MEMORY[DEVTAB[D+1]+LINTAB+LINE]],-1);
		    WORD ← 0;
		    FOR I ← 1 STEP 1 UNTIL 16 DO BEGIN "GET ONE WORD"
			FOR J ← 1 STEP 1 UNTIL 8 DO
			    WORD ← (WORD LSH 4) + ILDB(BP);
			INSERT((WORD LSH 4) + 2)	COMMENT 2 means graphic wrd;
			END "GET ONE WORD";
		COMMENT And now an execute command to draw the line;
		    INSERT('0224)			COMMENT exec. and 2 sel chn;
		END "LINE OUTPUT";

    COMMENT Finish up by putting in a halt instruction.;
	INSERT(0);

    COMMENT Now run the datadisc program and show the result to the user.;
	CTLBLK[0] ← LOCATION(DDBUF[0]);
	CTLBLK[1] ← DDBUFSIZE;
	QUICK_CODE
	    PGIOT 3,CTLBLK[0];	COMMENT That's pronounced "DDUPG";
	END;
	SHOWA(CHAN)
    END "DD OUTPUT";

[SYNTHESIZER] BEGIN "SYNTH OUTPUT"	COMMENT This is a lot like the DD, but 8x.;

	INTEGER CHAN,BP,I,J,BIT,MASK,WORD;
	INTEGER LINE,STARTLINE;

    COMMENT Start by setting up video intensity table and grabbing channels;
	SYNMAP(0,-1);
COMMENT Graycoding modifies this line;  MAPMON(1.0);
	BIT ← 0;
	WHILE (CHAN ← SYNMAP(BIT)) ≠ -1 DO BEGIN "OUTPUT ONE BIT"
print("Preparing bit ",bit," on channel ",synmap(bit),'15&'12);
	   BUFPTR ← 0;
	   INSERT((CHAN ROT -8) + (2 ROT -27)      COMMENT Select channel;
		+ (7 ROT -16) + (1 ROT -30)        COMMENT Set functions: dark back,
							   write enb, graphic mode;
		+ (2 ROT -33)                      COMMENT no-op (sel. ch. 0);
		+ 4);                              COMMENT Command word opcode;

       COMMENT Now display all the lines in 4 sets.  This is the only way the
	   timing will work properly on the Datadisc.;
	   FOR STARTLINE ← 0 STEP 1 UNTIL 3 DO
	       FOR LINE ← STARTLINE STEP 4 UNTIL 479 DO
		   BEGIN "LINE OUTPUT"
		       INSERT(((LINE LSH -4) ROT -8) + (4 ROT -27) COMMENT Hi line ad;
			    + ((LINE LAND '17) ROT -16) + (5 ROT -30) COMMENT Lo ad;
			    + (1 ROT -24) + (3 ROT -33)    COMMENT Select col 1;
			    + 4);                          COMMENT Command word;
		   COMMENT For each line, pick up the appropriate bits and plop
			   them into the DD buffer.  This is all done assuming an
			   8-bit picture.;
		       BP ← POINT(8,MEMORY[MEMORY[DEVTAB[D+1]+LINTAB+LINE]],-1);
COMMENT Graycoding modifies this line;  MASK ← 1 LSH (7-BIT);
		       WORD ← 0;	COMMENT WORD will accumulate a graphic word;
		       FOR I ← 1 STEP 1 UNTIL 16 DO BEGIN
			   FOR J ← 1 STEP 1 UNTIL 32 DO	   COMMENT Accumulate word;
			       WORD ← (WORD LSH 1) +
				      (IF (ILDB(BP) LAND MASK) ≠ 0 THEN 1 ELSE 0);
			   INSERT((WORD LSH 4) + 2)    COMMENT 2 means graphic wrd;
			   END;
		   COMMENT And now an execute command to draw the line;
		       INSERT('0224)                       COMMENT exec. and 2 sel chn;
		   END "LINE OUTPUT";

       COMMENT Finish up by putting in a halt instruction.;
	   INSERT(0);

       COMMENT Now run the datadisc program to output one bit.;
	   CTLBLK[0] ← LOCATION(DDBUF[0]);
	   CTLBLK[1] ← DDBUFSIZE;
	   QUICK_CODE
	       PGIOT 3,CTLBLK[0];  COMMENT That's pronounced "DDUPG";
	   END;
	   BIT ← BIT + 1
	END "OUTPUT ONE BIT";

    COMMENT Now display the synthesizer;
	SHOWA('47)
	END "SYNTH OUTPUT";

[PICTURE]				COMMENT Nothing to be done here...;

END "DEVICE CASES"
END "SEE";
INTERNAL PROCEDURE SETCLR(INTEGER C);
COMMENT Set color for all following graphics;
BEGIN "SETCLR"

COLOR ← C

END "SETCLR";
END "DEVIND"